<script lang="ts" setup>
import { inject, ref, watch, type Ref } from 'vue'
import { cloneDeep } from 'lodash'
export interface FormItem {
  field: string //字段
  type: 'input' | 'checkbox' | 'radio'
  prop: string //表单名
  value: string | number | Array<number> //数据内容：性别等单选框或多选框为数字
  attr?: {
    placeholder: string
  }
  // <Omit<FormItem, 'type' | 'prop'>：创建了一个新类型，排除了 FormItem 类型中的 type 和 prop 属性，保留了其他所有的属性。
  children?: Array<Omit<FormItem, 'type' | 'prop'> & { id?: string }>
}
export interface formValueItem {
  username: string
  password: string
  address: string
  phone: string
  gender: number
  roles: {
    id: number
    name: string
  }[]
}
defineOptions({
  name: 'formModal' //模态框表单
})

// 接收表单字段
const formSchema = inject('formSchema') as FormItem[]

// 生成一个随机字符串充当radio和checkbox的id
const rand = () => {
  // Math.random():生成0-1的随机小数 toString(36)转化为36进制的额字符串 substring(2) 表示从字符串的第 2 个字符开始提取子字符串
  return Math.random().toString(36).substring(2)
}
// 表单数据双向绑定
const formValue = ref({
  ...cloneDeep(
    formSchema.reduce(
      (prev, item) => {
        prev[item.prop] = item.value
        if (['radio', 'checkbox'].includes(item.type)) {
          item.children?.forEach((o) => {
            o.id = rand()
          })
        }
        return prev
      },
      {} as Record<string, string | number | Array<number>>
    )
  )
})
const emit = defineEmits(['change'])
// 接收tempItem
const tempItem = inject('tempItem') as Ref
watch(
  () => tempItem.value,
  () => {
    formValue.value = tempItem.value
    const profile = tempItem.value.profile || {}
    formValue.value.gender = profile.gender || 0
    formValue.value.address = profile.address || ''
    formValue.value.phone = profile.phone || ''
  },
  {
    deep: true
  }
)
// 监听formValue.value的变化
watch(
  () => formValue.value,
  () => {
    emit('change', formValue.value)
  },
  {
    deep: true
  }
)
// 清空表单数据
const clearFormValue = () => {
  formValue.value = cloneDeep(
    formSchema.reduce(
      (prve, item) => {
        prve[item.prop] = item.value
        return prve
      },
      {} as Record<string, string | number | Array<number>>
    )
  )
}
defineExpose({
  clearFormValue
})
</script>
<template>
  <!-- schema(json) => form结构 =>动态形成form表单组件 -->
  <form v-for="(item, index) in formSchema" :key="index">
    <!-- input -->
    <div class="mb-2" v-if="item.type === 'input'">
      <label for="usernameInp" class="form-label fs-6">{{ item.field }}</label>
      <input
        :type="item.type"
        class="form-control fs-6"
        id="usernameInp"
        :placeholder="item.attr?.placeholder"
        v-model="formValue[item.prop]"
      />
    </div>

    <!-- checkbox -->
    <div class="mb-2" v-else-if="item.type === 'checkbox'">
      <label class="form-label fs-6">{{ item.field }}</label>
      <div class="form-control border-0">
        <div
          class="form-check form-check-inline"
          v-for="(Ritem, index) in item.children"
          :key="index"
        >
          <input
            class="form-check-input"
            type="checkbox"
            :id="Ritem.id"
            :value="Ritem.value"
            v-model="formValue[item.prop]"
          />
          <label class="form-check-label" :for="Ritem.id">
            {{ Ritem.field }}
          </label>
        </div>
      </div>
    </div>
    <!-- radio：单选框 -->
    <div class="mb-2" v-else-if="item.type === 'radio'">
      <label class="form-label fs-6">{{ item.field }}</label>
      <div
        class="form-check form-check-inline"
        v-for="(Gitem, index) in item.children"
        :key="index"
      >
        <input
          class="form-check-input"
          type="radio"
          name="gender"
          :id="Gitem.id"
          :value="Gitem.value"
          v-model="formValue[item.prop]"
        />
        <label class="form-check-label fs-6" :for="Gitem.id">
          {{ Gitem.field }}
        </label>
      </div>
    </div>
  </form>
</template>
<style scoped></style>
